package mac10.roles;

import de.dailab.jiactng.agentcore.ontology.IAgentDescription;

import mac10.connection.MessageConstants;
import mac10.models.Cell;
import mac10.models.WorldModel;

public class Explorer extends AbstractRole {

	public Explorer(IAgentDescription thisAgent, WorldModel worldModel) {
		super(thisAgent, worldModel, true, true, false, false);
	}

	public String executeTask(WorldModel worldModel, String task, int posx,
			int posy, long deadline, boolean custom) {
		// dest = exp.getExpCell(agent, this.agents.get(agent), this.worldModel,
		// this.simulationStep);
	    this.worldModel = worldModel;
	    
	    String action = exploreDirectly(worldModel, posx, posy, deadline);
	    if(action != null)
	    {
//	        System.out.println("Direct explore move from ("+posx+", "+posy+") to "+action);
	        return action;
	    }
	    
		Cell dest = MasterExplorer.nextUnknownCell(this.worldModel.getCell(
				posx, posy), this.simulationStep);
		action = this.getAction(posx, posy, deadline, dest);

		
		return action;
	}
	
	private String exploreDirectly(WorldModel worldModel, int posx, int posy, 
	        long deadline)
	{
	    int sight = worldModel.getLineOfSight()+1;
	    int width = worldModel.getWidth();
	    int height = worldModel.getHeight();
	    int[] counter = new int[8];
	    
	    //check if directions are accessible
	    if(posy-1 < 0 || !worldModel.getCell(posx, posy-1).isAccessible())
	        counter[0] = Integer.MIN_VALUE;
        if(posx+1 >= width || posy-1 < 0 || !worldModel.getCell(posx+1, posy-1).isAccessible())
            counter[1] = Integer.MIN_VALUE;
        if(posx+1 >= width || !worldModel.getCell(posx+1, posy).isAccessible())
            counter[2] = Integer.MIN_VALUE;
        if(posx+1 >= width || posy +1 >= height || !worldModel.getCell(posx+1, posy+1).isAccessible())
            counter[3] = Integer.MIN_VALUE;
        if(posy +1 >= height || !worldModel.getCell(posx, posy+1).isAccessible())
            counter[4] = Integer.MIN_VALUE;
        if(posx-1 < 0 || posy +1 >= height || !worldModel.getCell(posx-1, posy+1).isAccessible())
            counter[5] = Integer.MIN_VALUE;
        if(posx-1 < 0 || !worldModel.getCell(posx-1, posy).isAccessible())
            counter[6] = Integer.MIN_VALUE;
        if(posx-1 < 0 || posy-1 < 0 || !worldModel.getCell(posx-1, posy-1).isAccessible())
            counter[7] = Integer.MIN_VALUE;
	    
        //counting the unknown cells that would be explored by the move
	    if(posy - sight >=0)
	    {
            for (int x = -sight; x <= sight; x++)
            {
                if(posx+x >= 0 && posx+x < width && worldModel.getCell(posx + x, posy - sight).isUnknown())
                {
                    if(x>-sight && x<sight)
                        counter[0]++;
                    if(x > -sight +1)
                        counter[1]++;
                    if(x < sight -1)
                        counter[7]++;
                }
            }
	    }
        if(posy + sight >=0 && posy + sight < height)
        {
            for (int x = -sight; x <= sight; x++)
            {
                if(posx+x >= 0 && posx+x < width && worldModel.getCell(posx + x, posy + sight).isUnknown())
                {
                    if(x>-sight && x<sight)
                        counter[4]++;
                    if(x > -sight+1)
                        counter[3]++;
                    if(x < sight-1)
                        counter[5]++;
                }
            }
        }
        if(posx + sight >=0 && posx + sight < width)
        {
    	    for (int y = -sight; y <= sight; y++)
    	    {
    	        if(posy+y >= 0 && posy+y < height && worldModel.getCell(posx + sight, posy + y).isUnknown())
    	        {
    	            if(y>-sight && y<sight)
    	                counter[2]++;
                    if(y > -sight+1 && y < sight)
                        counter[3]++;
                    if(y > -sight && y < sight-1)
                        counter[1]++;
    	        }
    	    }
        }
        if(posx - sight >=0 && posx - sight < width)
        {
    	    for (int y = -sight; y <= sight; y++)
            {
                if(posy+y >= 0 && posy+y < height && worldModel.getCell(posx - sight, posy + y).isUnknown())
                {
                    if(y>-sight && y<sight)
                        counter[6]++;
                    if(y > -sight+1 && y < sight)
                        counter[5]++;
                    if(y > -sight && y < sight-1)
                        counter[7]++;
                }
            }
        }
        
        // get the best move
	    int maxIndex = 0;
	    int max = counter[0];
	    for (int i = 1; i < counter.length; i++)
        {
            if(counter[i] > max)
            {
                max = counter[i];
                maxIndex = i;
            }
        }
	    
	    // no direct explore possible
	    if (max <= 0)
	        return null;
	    
	    switch (maxIndex) {
	    case 0: return MessageConstants.ACTION_NORTH;
	    case 1: return MessageConstants.ACTION_NORTHEAST;
        case 2: return MessageConstants.ACTION_EAST;
        case 3: return MessageConstants.ACTION_SOUTHEAST;
        case 4: return MessageConstants.ACTION_SOUTH;
        case 5: return MessageConstants.ACTION_SOUTHWEST;
        case 6: return MessageConstants.ACTION_WEST;
        case 7: return MessageConstants.ACTION_NORTHWEST;
        
        default: return null;//should never be the case
	    }
	}

	public String toString() {
		return "explorer";
	}
}
